package com.ruoyi.jt808.util.abandon;

import com.ruoyi.common.utils.OpenStreetMapUtil;

/**
 * WGS84坐标系 与 GCJ02（火星坐标系） 之间的转换
 * 参考自：https://github.com/wandergis/coordtransform 及其他开源项目
 */
public class CoordinateTransform {

    // 圆周率 π
    private static final double PI = Math.PI;
    // 长半轴 (WGS84坐标系)
    private static final double AXIS = 6378245.0;
    // 偏心率平方
    private static final double OFFSET = 0.00669342162296594323;
    // 转换参数
    private static final double PARAM = 1.5;

    /**
     * 判断坐标是否在中国范围内
     * @param lng 经度
     * @param lat 纬度
     * @return true: 在中国范围内，需要转换; false: 不在中国范围内，无需转换
     */
    public static boolean isInChina(double lng, double lat) {
        if (lng < 72.004 || lng > 137.8347) {
            return false;
        }
        if (lat < 0.8293 || lat > 55.8271) {
            return false;
        }
        return true;
    }

    /**
     * 转换单点坐标：WGS84 -> GCJ02
     * @param lng 经度
     * @param lat 纬度
     * @return 包含GCJ02经纬度的double数组，[0]为经度，[1]为纬度
     */
    public static double[] transformWGS84ToGCJ02(double lng, double lat) {
        double[] result = new double[2];

        // 如果不在中国范围内，直接返回原坐标
        if (!isInChina(lng, lat)) {
            result[0] = lng;
            result[1] = lat;
            return result;
        }

        // 计算偏移量
        double[] offset = calculateOffset(lng, lat);
        double dlng = offset[0];
        double dlat = offset[1];

        // 加上偏移量
        double gcjLng = lng + dlng;
        double gcjLat = lat + dlat;

        result[0] = gcjLng;
        result[1] = gcjLat;
        return result;
    }

    /**
     * 计算WGS84坐标与GCJ02坐标之间的偏移量
     * @param lng 经度
     * @param lat 纬度
     * @return 偏移量数组，[0]为经度偏移量，[1]为纬度偏移量
     */
    private static double[] calculateOffset(double lng, double lat) {
        double[] offset = new double[2];
        double dlng = transformLng(lng - 105.0, lat - 35.0);
        double dlat = transformLat(lng - 105.0, lat - 35.0);
        double radLat = lat / 180.0 * PI;
        double magic = Math.sin(radLat);
        magic = 1 - OFFSET * magic * magic;
        double sqrtMagic = Math.sqrt(magic);
        dlng = (dlng * 180.0) / (AXIS / sqrtMagic * Math.cos(radLat) * PI);
        dlat = (dlat * 180.0) / ((AXIS * (1 - OFFSET)) / (magic * sqrtMagic) * PI);
        offset[0] = dlng;
        offset[1] = dlat;
        return offset;
    }

    /**
     * 转换经度
     */
    private static double transformLng(double lng, double lat) {
        double ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
        ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
        ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
        return ret;
    }

    /**
     * 转换纬度
     */
    private static double transformLat(double lng, double lat) {
        double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
        ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
        ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
        return ret;
    }

    // 示例用法
    public static void main(String[] args) {
        // 示例：北京某个点的WGS84坐标 (例如从GPS获取)
        double wgs84Lng = 107.565364;
        double wgs84Lat = 33.217993;

        System.out.println("原始 WGS84 坐标: " + wgs84Lng + ", " + wgs84Lat);

        double[] gcj02 = transformWGS84ToGCJ02(wgs84Lng, wgs84Lat);

        System.out.println("转换后 GCJ02 坐标: " + gcj02[0] + ", " + gcj02[1]);

        OpenStreetMapUtil.getLocatin(gcj02[0]+","+gcj02[1]);
    }
}
